import axios from 'axios';
import qs from 'qs';

import { EE, UN_LOGIN } from './emitter';
import { ERROR_CODE_MAP } from '@/config';
import { REFRESH_TOKEN_URL } from '@/config/url';

// Token刷新功能开关
let enableTokenRefresh = false;

// Token刷新相关状态
let isRefreshing = false;
let failedQueue = [];

// 缓存常用的HTTP方法数组，避免重复创建
const GET_DELETE_METHODS = ['GET', 'DELETE'];
const POST_PUT_PATCH_METHODS = ['POST', 'PUT', 'PATCH'];

// 缓存localStorage键名，避免字符串重复创建
const ACCESS_TOKEN_KEY = 'accessToken';
const REFRESH_TOKEN_KEY = 'refreshToken';

// 处理队列中的请求
const processQueue = (error, token = null) => {
    failedQueue.forEach(({ resolve, reject }) => {
        if (error) {
            reject(error);
        } else {
            resolve(token);
        }
    });
    failedQueue = [];
};

// 刷新token的函数
const autoRefreshToken = async () => {
    try {
        const rToken = localStorage.getItem(REFRESH_TOKEN_KEY);
        if (!rToken) throw new Error('refreshToken 不可用');

        const response = await axios.post(REFRESH_TOKEN_URL, { refreshToken: rToken });
        const code = response?.data?.code?.toString();
        if (OK_CODE === code) {
            const { accessToken, refreshToken: newRefreshToken } = response.data.data;
            
            localStorage.setItem(ACCESS_TOKEN_KEY, accessToken);
            if (newRefreshToken) localStorage.setItem(REFRESH_TOKEN_KEY, newRefreshToken);
            
            return accessToken;
        }

        throw new Error('accessToken 刷新失败');
    } catch (error) {
        localStorage.removeItem(ACCESS_TOKEN_KEY);
        localStorage.removeItem(REFRESH_TOKEN_KEY);
        throw error;
    }
};

// 创建 axios 实例
const axiosInstance = axios.create({
    timeout: 1000*60,
});

// 请求拦截器
axiosInstance.interceptors.request.use(
    (config) => {
        const accessToken = localStorage.getItem(ACCESS_TOKEN_KEY);
        if (accessToken) config.headers.token = accessToken;
        return config;
    },
    (error) => {
        return Promise.reject(error);
    }
);

// 响应拦截器
axiosInstance.interceptors.response.use(
    (response) => {
        if (200 === response.status) {
            const { code = '', data = null, message = '' } = response.data || {};
            
            if (OK_CODE === code.toString()) return {...response.data, code: code.toString()};
            
            return Promise.reject({
                code: code.toString(),
                data,
                message: message || '请求失败'
            });
        }
        
        return Promise.reject({
            code: (response.status || 500).toString(),
            data: null,
            message: '网络异常'
        });
    },
    async (error) => {
        const originalRequest = error.config;
        
        // 处理401未授权错误
        if (UNAUTHORIZED_CODE === error.response?.data?.code?.toString()) {
            // 如果未启用token刷新功能，直接触发登录过期事件
            if (!enableTokenRefresh) {
                EE.emit(UN_LOGIN, originalRequest);
                return Promise.reject({
                    code: UNAUTHORIZED_CODE,
                    data: null,
                    message: '登录已过期，请重新登录'
                });
            }
            
            if (originalRequest._retry) {
                EE.emit(UN_LOGIN, originalRequest);
                return Promise.reject({
                    code: UNAUTHORIZED_CODE,
                    data: null,
                    message: '登录已过期，请重新登录'
                });
            }
            
            // 如果正在刷新token，将请求加入队列
            if (isRefreshing) {
                return new Promise((resolve, reject) => {
                    failedQueue.push({ resolve, reject });
                }).then(() => {
                    const accessToken = localStorage.getItem(ACCESS_TOKEN_KEY);
                    originalRequest.headers.token = accessToken;
                    return axiosInstance(originalRequest);
                }).catch(err => {
                    return Promise.reject(err);
                });
            }
            
            originalRequest._retry = true;
            isRefreshing = true;
            
            try {
                const newToken = await autoRefreshToken();
                processQueue(null, newToken);
                
                originalRequest.headers.token = newToken;
                return axiosInstance(originalRequest);
                
            } catch (refreshError) {
                processQueue(refreshError, null);
                EE.emit(UN_LOGIN, originalRequest);
                
                return Promise.reject({
                    code: UNAUTHORIZED_CODE,
                    data: null,
                    message: '登录已过期，请重新登录'
                });
            } finally {
                isRefreshing = false;
            }
        }
        
        const errorMessage = ERROR_CODE_MAP[error?.code?.toString()] || error.message || '服务异常，请稍后重试';
        
        return Promise.reject({
            code: (error.response?.status || error.status || 500).toString(),
            data: null,
            message: errorMessage
        });
    }
);

// 导出request函数，直接返回[data, error]格式
export default async function request(url, options = {}) {
    try {
        const {
            method = 'GET',
            data = {},
            contentType,
            responseType = 'json',
            timeout,
            onUploadProgress,
            signal
        } = options;
        
        const upperMethod = method.toUpperCase();
        const isUrlEncoded = contentType === 'application/x-www-form-urlencoded';
        // 判断是否为 FormData：直接检测 data 是否为 FormData 实例
        const isFormData = data instanceof FormData;
        const responseBlob = responseType === 'blob';
        
        const config = {
            url,
            method: upperMethod,
            responseType,
            signal
        };
        
        if (timeout) config.timeout = timeout;
        // 对于 multipart/form-data，不手动设置 Content-Type，让浏览器自动设置包含正确 boundary 的头部
        // 手动设置可能会覆盖自动生成的 boundary 参数，导致请求失败
        if (!isFormData) {
            config.headers = config.headers || {};
            config.headers['Content-Type'] = contentType || 'application/json';
        }
        if (onUploadProgress && 'function' === typeof onUploadProgress) config.onUploadProgress = onUploadProgress;
        
        // 处理GET/DELETE请求的查询参数
        if (GET_DELETE_METHODS.includes(upperMethod) && data && Object.keys(data).length > 0) {
            const separator = url.includes('?') ? '&' : '?';
            config.url = `${url}${separator}${qs.stringify(data)}`;
        } else if (POST_PUT_PATCH_METHODS.includes(upperMethod)) {
            if (isUrlEncoded) {
                config.data = qs.stringify(data);
            } else if (isFormData) {
                config.data = data;
            } else {
                // 注意，如果key的值是undefined，那么这个key在提交时会被丢弃
                config.data = JSON.stringify(data);
            }
        }
        
        const response = await axiosInstance(config);
        
        if (responseBlob && response.data instanceof Blob) return [response.data, null];
        return [response, null];
    } catch (error) {
        return [null, error];
    }
}